#ifndef SINT_H_INCLUDED
#define SINT_H_INCLUDED

#include <iostream>
#include <stdexcept>
#include <pthread.h>
#include "Debug.h"

using namespace std;

#define SYNCHRONISED_INT
#ifdef SYNCHRONISED_INT
class Synchronised_Int
{
    int m_int;
    pthread_mutex_t m_mutex;
public:
    Synchronised_Int(int _int = 0) : m_int(_int) {
        if(pthread_mutex_init(&m_mutex, NULL)) {
            throw runtime_error("Synchronised_Int:Synchronised_Int() : failed to initialize mutex");
        }
    }

    operator int () {
        pthread_mutex_lock (&m_mutex);
        int temp = m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator + (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp + op2;
    }

    int operator - (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp + op2;
    }

    int operator * (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp * m_int;
    }

    int operator / (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp / op2;
    }

    int operator ++ () {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = ++m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator -- () {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = --m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator ++ (int dummy) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int++;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator -- (int dummy) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int--;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator += (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = (m_int += op2);
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator -= (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = (m_int -= op2);
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator *= (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = (m_int *= op2);
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator /= (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = (m_int /= op2);
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator = (int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int = op2;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }

    int operator = (Synchronised_Int op2) {
        int temp;
        pthread_mutex_lock (&m_mutex);
        temp = m_int = op2.m_int;
        pthread_mutex_unlock (&m_mutex);
        return temp;
    }


    ~Synchronised_Int() {
        pthread_mutex_destroy(&m_mutex);
    }
};

typedef Synchronised_Int SyInt;

#else

#define Synchronised_Int int;
#define Sint int;

#endif

#endif // SINT_H_INCLUDED
